#include "task.hpp"
#include "blockqueue.hpp"
#include <ctime>
#include <unistd.h>
#include <pthread.h>
template <class C, class S>
class BlockQueues
{
public:
    BlockQueue<C> *c_bq;
    BlockQueue<S> *s_bq;
};
void *productor(void *bqs_)
{
    BlockQueue<CalTask> *bq = static_cast<BlockQueues<CalTask, SaveTask> *>(bqs_)->c_bq;
    while (true)
    {
        int x = rand() % 10 + 1;
        int y = rand() % 5;
        int operCode = rand() % oper.size();
        CalTask t(x, y, oper[operCode], mymath);
        bq->push(t);
        printf("productor thread, 生产计算任务 : %s\n", t.toTaskString().c_str());
        sleep(1);
    }
    return nullptr;
}
void *consumer(void *bqs_)
{
    BlockQueue<CalTask> *bq = static_cast<BlockQueues<CalTask, SaveTask> *>(bqs_)->c_bq;
    BlockQueue<SaveTask> *save_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(bqs_)->s_bq;
    while (true)
    {
        CalTask t;
        bq->pop(&t);
        std::string result = t();
        printf("cal thread, 完成计算任务 : %s...done\n", result.c_str());
        SaveTask s(result, save);
        save_bq->push(s);
        printf("cal thread, 推送存储任务完成...\n");
    }
    return nullptr;
}
void *saver(void *bqs_)
{
    BlockQueue<SaveTask> *save_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(bqs_)->s_bq;
    while (true)
    {
        SaveTask s;
        save_bq->pop(&s);
        s();
        printf("save thread, 保存任务完成...\n");
    }
    return nullptr;
}
int main()
{
    srand((unsigned long)time(nullptr) ^ getpid());
    BlockQueues<CalTask, SaveTask> bqs;
    bqs.c_bq = new BlockQueue<CalTask>();
    bqs.s_bq = new BlockQueue<SaveTask>();
    pthread_t p, c, s;
    pthread_create(&p, nullptr, productor, (void *)&bqs);
    pthread_create(&c, nullptr, consumer, (void *)&bqs);
    pthread_create(&s, nullptr, saver, (void *)&bqs);
    pthread_join(p, nullptr);
    pthread_join(c, nullptr);
    pthread_join(s, nullptr);
    delete bqs.c_bq;
    delete bqs.s_bq;
    return 0;
}